//
//	IOBUS - The Big Include
//
//  (c) 2008,2009 mocom software GmbH & Co KG
//
//  $Author: volker $
//  $Date: 2009-10-01 18:51:54 +0200 (Do, 01. Okt 2009) $
//  $Revision: 509 $
//
//  MOCOM CONFIDENTIAL
//
//-----------------------------------------------------------------------------

#ifndef DEF_NO_BASIC_TYPES
typedef unsigned long long UINT64;
typedef unsigned long UINT32;
typedef unsigned short UINT16;
typedef unsigned char UINT8;
typedef long long INT64;
typedef long INT32;
typedef short INT16;
typedef signed char INT8;
#endif

#define IOBUS_BAUDRATE				115200
//#define IOBUS_BAUDRATE				57600
#define IOBUS_INTERMESSAGEGAP		2

#define IOBUS_MAX_OBJECTS			16
#define IOBUS_MAX_DATA_LENGTH		((IOBUS_MAX_OBJECTS+1)*4)
#define IOBUS_INTER_FRAME_GAP		2
#define IOBUS_MIN_FRAME_LENGTH		4
#define IOBUS_MAX_FRAME_LENGTH		(IOBUS_MAX_DATA_LENGTH+IOBUS_MIN_FRAME_LENGTH)
#define IOBUS_TIMEOUT_PAD			4
// for now, future versions will not need this
#define IOBUS_DEAD_TIME				300

#define IOBUS_MAX_MESSAGE_LENGTH	(IOBUS_MAX_FRAME_LENGTH+IOBUS_INTER_FRAME_GAP)
#define IOBUS_MIN_MESSAGE_LENGTH	(IOBUS_MIN_FRAME_LENGTH+IOBUS_INTER_FRAME_GAP)


#define IOBUS_MAX_NODES				32

#ifndef PRIVATE
#define PRIVATE	static
#endif

#ifndef NULL
#define NULL	0
#endif

#ifndef FALSE
#define FALSE	0
#endif

#ifndef TRUE
#define TRUE	(!FALSE)
#endif



typedef enum
{
	IO_ADDR_Broadcast = 0xff,
	IO_ADDR_Master2Slave = 0xe0,
	IO_ADDR_Slave2Master = 0xa0,
	IO_ADDR_Ctrl_Mask = 0xe0,
	IO_ADDR_Mask = 0x01f,
} IOBusAddrCodes;


typedef struct IOBUS_statistics
{
	UINT32		aborted;			// a ongoing receiption was broken
	UINT32		sync_error;			// a rx started with a missformed uart char
	UINT32		rxstarted;			// a rx started correctly
	UINT32		address_mismatch;	// address fail
	UINT32		msgtype_mismatch;	// msg type error
	UINT32		coding_error;		// coding error
	UINT32		len_error;			// len wrong
	UINT32		crc_error;			// crc error
} IOBusStatistics;

typedef enum
{
	IO_ERR_Ok = 0,				// cmd executed
	IO_ERR_Slip1 = 0x1,			// device cycle miss
	IO_ERR_Slip2 = 0x2,			// device cycle miss
	IO_ERR_Pwr = 0x4,				// power fail
	IO_ERR_WD = 0x8,				// watch dog
	IO_ERR_TIMEOUT = 0x10,		// not ready (master)
	IO_ERR_NotRdy = 0x10,			// not ready (slave)
	IO_ERR_Objects = 0x20,		// IO-Objects have errors, use IOReadErrors
	IO_ERR_FATAL_CLASS = ( IO_ERR_WD | IO_ERR_Pwr | IO_ERR_Slip2 ),
	IO_ERR_MASK = 0x3f,
	// --- API ONLY
	IO_ERR_FATAL_TOUT = -1,			// master intern only
	IO_ERR_Len = -2,
	IO_ERR_OVERRUN = -3,
	IO_ERR_ENABLEFAILED = -4,
} IOBusErrorCodes;

typedef enum
{
	IO_DATA_No = 0x00, 			// no data
	IO_DATA_Yes = 0x40,			// data & len
	IO_CMDRES_Mask = 0x3f,		// comres mask
} IOBusDataMasks;

typedef enum
{
	IO_CMD_SysReadId = 0,			// read type + S/N
	IO_CMD_EmStop = 1,			// issue emergency stop.
	// 2,3 reserved for cfg
	IO_CMD_Tick = 4,				// capture I/O
	IO_CMD_Update = 5,			// read captured I/O, write physical I/O
	IO_CMD_ReadInfo = 6,			// read object info
	IO_CMD_ReadError = 7,			// read error status
	IO_CMD_ReadStatistics = 8,	// read statistic counters
	// 9..13 reserved
	// IO_CMD_ProgUpdate=14,		// write & verify program memory, addr in first 4 bytes of data
	// IO_CMD_ProgErase=15,		// erase firmware program
} IOBusCmdCodes;

typedef struct IOBUS_frame
{
	UINT8	addr;
	UINT8	cmdres;
	UINT8	cycle;
	UINT8	crc;
	UINT8	len;
	UINT8	data[IOBUS_MAX_DATA_LENGTH];
	UINT8	crc16pad[2];
} IOBusFrame;

//-----------------------------------------------------------------------------
//	IOBUS OBJECT DIRECTORY
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
//	Datatypes
// 	- ANALOG
//  - DIGITAL VECTOR
//  - OTHER
//
//	ID	+------+----+-----+---+-----+
//		| TYPE | IN | OUT | E | phy |
//		+------+----+-----+---+-----+
//
//		TYPE = {OBJ_IS_DIGITAL, OBJ_IS_ANALOG, OBJ_IS_COUNTER}, 6-Bit
//		IN	 = is INPUT, 1-bit
//		OUT  = is OUTPUT, 1-bit
//		E    = 8-Bit intger exponent
// 		phy  = 16 bit physical unit
//
//		Example:	0..20mA input: 		type=analog, input=1, output=0, i=0, e=-3 phy=AMPERE
//		Example:	-40..+120°C input: 	type=analog, input=1, output=0, i=0, e=0, phy=CELSIUS
// 		Example:	0..31 digi, output:	type=digital, input=1, output=1, i=1, e=0, phy=RAW
// 		Example:	0..1^32-1 digi counter, input:	type=counter, input=1, output=1, e=0, phy=RAW
//
#define OBJ_CLASS_MASK		((0x03000000))
#define OBJ_IS_OUTPUT		((1<<24))
#define OBJ_IS_INPUT		((1<<25))			// there are inputs and outpust, nothing else

#define OBJ_TYPE_MASK		((0xfc000000))
#define OBJ_IS_DIGITAL		((1<<26))			// digital bitmap
#define OBJ_IS_ANALOG		((2<<26))			// analog value, float
#define OBJ_IS_COUNTER		((3<<26))			// counter value, integer

#define OBJ_EXP_MASK		((0x00ff0000))
#define OBJ_EXP_SHIFT		(16)				

#define OBJ_UNIT_MASK		((0x0000ffff))
#define OBJ_UNIT_RAW		(0)
#define OBJ_UNIT_AMPERE		(1)
#define OBJ_UNIT_VOLT		(2)
#define OBJ_UNIT_OHM		(3)
#define OBJ_UNIT_WATT		(4)
#define OBJ_UNIT_JOULE		(5)
#define OBJ_UNIT_KELVIN		(6)
#define OBJ_UNIT_CELSIUS	(7)
#define OBJ_UNIT_S0PULSE	(8)

typedef union
{
	float	fvalue;
	UINT32	ivalue;
} IOBusObjectValue;

enum {objectOK, objectUpdated};

typedef int ( *OBJDIR_WRITE_CALLBACK )( unsigned idx, void *arg, IOBusObjectValue value );

typedef struct
{
	UINT32				id;			// type id
	UINT16				tag;		// tag of last action
	UINT8				error;		// error code
	UINT8				updated;	// update flag
	IOBusObjectValue	invalue;	// value related to tag
	IOBusObjectValue	outvalue;	// out value
	IOBusObjectValue	defvalue;	// default value
	OBJDIR_WRITE_CALLBACK	write;	// callback, write I/O to physical port
	void				*arg;		// callback argument
} IOBusObject;

typedef struct
{
	unsigned	entries;
	IOBusObject	objects[IOBUS_MAX_OBJECTS];
} IOBusObjectDir;

typedef struct
{
	UINT32				valid;
	IOBusObjectValue	values[IOBUS_MAX_OBJECTS];
} IOBusObjectWireImage;

void IOBusObjectChangeUnits( IOBusObjectDir *dir, unsigned idx, unsigned phyunit, int exp );
int IOBusObjectSetCallback( IOBusObjectDir *dir, unsigned idx, int ( *write )(), void *arg );
unsigned IOBusObjectSerialize( IOBusObjectDir *dir, IOBusObjectWireImage *wire, unsigned tag, unsigned *error, unsigned long classes );
void IOBusObjectDeSerialize( IOBusObjectDir *dir, IOBusObjectWireImage *wire, unsigned tag );
int IOBusObjectSerializeInfo( IOBusObjectDir *dir, IOBusObjectWireImage *wire );
void IOBusObjectDeSerializeInfo( IOBusObjectDir *dir, IOBusObjectWireImage *wire, unsigned tag );
int IOBusObjectSerializeError( IOBusObjectDir *dir, IOBusObjectWireImage *wire );
void IOBusObjectDeSerializeError( IOBusObjectDir *dir, IOBusObjectWireImage *wire );
int IOBusObjectWriteData( IOBusObjectDir *dir, unsigned idx, IOBusObjectValue *value, unsigned tag );
int IOBusObjectReadData( IOBusObjectDir *dir, unsigned idx, IOBusObjectValue *value, unsigned *tag );
int IOBusObjectError( IOBusObjectDir *dir, unsigned idx, UINT32 errorcode );
int IOBusObjectPrint( IOBusObjectDir *dir, unsigned idx, int debug );
int IOBusObjectDirAdd( IOBusObjectDir *dir, int type, int inout, int exp, int phy, IOBusObjectValue *value, OBJDIR_WRITE_CALLBACK writefn, void *arg );

//-----------------------------------------------------------------------------
//	HAL LAYER
//-----------------------------------------------------------------------------

void IOBUS_Initialize();
void IOBUS_Uninitialize();

void IOBusHalStartCapture( IOBusObjectDir *dir, unsigned tag );
void IOBusHalEMStop( IOBusObjectDir *dir, unsigned tag );
void IOBusHalSendData( UINT8 *data, unsigned len );
int  IOBusHalGapDetected( int hunt );
void IOBusHalStartTimeout( unsigned long t );
void IOBusHalStartTimer( unsigned long ctimes );
void IOBusHalStopTimeout( void );
int  IOBusTimeout( void );
void *IOBusHalMemoryCopy( void *d, void *s, unsigned l );
void IOBusHalMemorySet( void *d, int val, unsigned len );
int  IOBusHALGetStrLen( char *s );
int  IOBusHALReady();
UINT64 IOBusHalGetTime();
int IOBusHalGetVersionString (UINT8 *ins);

int IOBusGetStatus( UINT8 node );
int IOBusCycle();
IOBusObjectDir *IOBusGetSlaveDir();
void IOBusIndicate( IOBusFrame *frame );
void IOBusSlave( IOBusFrame *frame );
void IOBusKickApiError( unsigned node, int error );
void IOBusKickApi( unsigned node, int error );
void IOBusSetCycleMode(int mode);
void IOBusMasterInit( unsigned long config, unsigned cycle_in_ms);
static IOBusObject *get_object( int node, int obj );
int IOBusMasterIndication( IOBusFrame *frame );

//-----------------------------------------------------------------------------
//	MASTER API
//-----------------------------------------------------------------------------
int IOBusEnable( unsigned long config );
int IOBusMasterEnabledState ();
int IOBusMasterGetNodeState( int node );
int IOBusMasterGetObjects( int node );
int IOBusMasterGetClass( int node, int objidx );
int IOBusMasterGetType( int node, int objidx );
int IOBusMasterGetExponent( int node, int objidx ); 
int IOBusMasterGetPhysicalUnit( int node, int objidx );
int IOBusMasterGetValue( int node, int objidx, IOBusObjectValue *value );
int IOBusMasterSetValue( int node, int objidx, IOBusObjectValue *value );

//-----------------------------------------------------------------------------
//	LINK LAYER
//-----------------------------------------------------------------------------

void IOBusInitLinkLayer( UINT8 node );
int IOBusSendNative( UINT8 *data, unsigned len );
void IOBusRxAssemble( unsigned chr, int error );
int IOBusSendCmd( UINT8 node, UINT8 cmdres, UINT8 cycle, UINT8 len, UINT8 *data );
IOBusStatistics *IOBusGetStatisticsPtr();

//-----------------------------------------------------------------------------
// 	CRC16
//-----------------------------------------------------------------------------
UINT16 CRC16Step( UINT8 data, UINT16 crc );
UINT16 CRC16Block( UINT8 *data, UINT16 length, UINT16 crc );


// aux
// Bit Definitions
#define BIT0  0x00000001
#define BIT1  0x00000002
#define BIT2  0x00000004
#define BIT3  0x00000008
#define BIT4  0x00000010
#define BIT5  0x00000020
#define BIT6  0x00000040
#define BIT7  0x00000080
#define BIT8  0x00000100
#define BIT9  0x00000200
#define BIT10 0x00000400
#define BIT11 0x00000800
#define BIT12 0x00001000
#define BIT13 0x00002000
#define BIT14 0x00004000
#define BIT15 0x00008000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define BIT18 0x00040000
#define BIT19 0x00080000
#define BIT20 0x00100000
#define BIT21 0x00200000
#define BIT22 0x00400000
#define BIT23 0x00800000
#define BIT24 0x01000000
#define BIT25 0x02000000
#define BIT26 0x04000000
#define BIT27 0x08000000
#define BIT28 0x10000000
#define BIT29 0x20000000
#define BIT30 0x40000000
#define BIT31 0x80000000
